#include "histo.h"

// Constructeur de la classe Histogramme par Défaut
Histogramme::Histogramme() {

    this->largeur=0;
    this->hauteur=0;
    this->img=Image();
    this->histo=Histogramme::setHisto_blanc();
    this->histo_cumul=Histogramme::setHisto_blanc();
    this->max_pixel=0;
}

// Constructeur de la classe Histogramme ne prenant que la largeur et la hauteur
Histogramme::Histogramme(int l, int h) {
    this->largeur=l;
    this->hauteur=h;
    this->img=Image();
    this->histo=Histogramme::setHisto_blanc();
    this->histo_cumul=Histogramme::setHisto_blanc();
    this->max_pixel=0;
}

// Constructeur de la classe Histogramme prenant la largeur, la hauteur et l'image
Histogramme::Histogramme(int l, int h, Image img) {
    this->largeur=l;
    this->hauteur=h;
    this->img=img;
    this->histo=Histogramme::setHisto_blanc();
    this->histo_cumul=Histogramme::setHisto_blanc();
    this->max_pixel=0;
}

// retourne la hauteur de l'image
int Histogramme::getHauteur() {
    return hauteur;
}

// retourne la largeur de l'image
int Histogramme::getLargeur() {
    return largeur;
}

// retourne l'image de l'histogramme
Image Histogramme::getHisto() {
    return histo;
}

// retourne l'image de l'histogramme cumulé
Image Histogramme::getHisto_cumul() {
    return histo_cumul;
}

// permet de fixer la hauteur de l'image
void Histogramme::setHauteur(int h) {
    hauteur=h;
}

// permet de fixer la largeur de l'image
void Histogramme::setLargeur(int l) {
    largeur=l;
}

// permet de créer l'image de l'histogramme à partir d'une image et d'un mode
// le mode correspond à la couleur que l'on souhaite traiter
// 1 : gris
// 2 : bleu
// 3 : vert
// 4 : rouge
void Histogramme::setHisto(Image img, int mode) {
    // creation de l'image en remplissant l'ensemble des pixels en blanc
    histo= Histogramme::setHisto_blanc();

    int x, y, i;

    // construit le tableau contenant la fréquence des couleurs de l'image
    // utilisation de l'entier "mode" pour définir la couleur que l'on souhaite traiter
    this->remplirTab(img, mode);

    // récupère le nombre maximum de pixel d'une couleur
    max_pixel = this->getMax();

    // calcule du coefficient pour que le pixel maximum arrive tout en haut de l'image (correspond à l'echelle)
    double coef = max_pixel/250;
    int value=0;

    // creation de l'image de l'histogramme
    for(i=0;i<256;i++) {
        // récupère le nombre de pixel pour la couleur
        value = tabPixel[i];
        // applique le coefficient
        value=int(value/coef);

        // applique un décalage pour ne pas commencer  le dessin dès le bord de l'image
        x=20+i;
        // y=275 pour appliquer un décalage en hauteur afin de que l'image soit centré
        for(y=275;y>255-value;y--) {
            // fixe les pixels en noir afin de créer la barre de l'histogramme
            histo.setPixel(x, y, qRgb(0,0,0));
        }

    }


}

// permet de construire l'histogramme cumulé à partir d'une image et d'un mode
// le mode correspond à la couleur que l'on souhaite traiter
// 1 : gris
// 2 : bleu
// 3 : vert
// 4 : rouge
void Histogramme::setHisto_cumul(Image img, int mode) {
    // création d'une image rempli de pixels blancs
    histo_cumul=Histogramme::setHisto_blanc();

    int x, y, i;

    // remplit le tableau par rapport à la couleur souhaité
    this->remplirTab(img, mode);

    // etant un histogramme cumulé, le coef se calcule à partir du nombre
    // total de pixel, soit la hauteur * largeur
    double coef = (img.width()*img.height())/255;
    int value=0;

    int z =0;
    
    for(i=0;i<256;i++) {
        // récupère le nombre de pixel cumulé du tableau jusque l'élément i
        z = this->getPixelCumul(i);
        // application  du coefficient
        value=z/coef;
        // application du décalage horizontale
        x=20+i;

        // y=275, application du décalage verticale
        for(y=275;y>255-value;y--) {
            histo_cumul.setPixel(x, y, qRgb(0,0,0));
        }

    }

}

// remplit la tableau par rapport à l'image et au mode
// le mode correspond à la couleur que l'on souhaite traiter
// 1 : gris
// 2 : bleu
// 3 : vert
// 4 : rouge
void Histogramme::remplirTab(Image img, int mode) {
    int i, x, y , indice=0;
    // initialisation du tableau à 0
    for(i=0;i<256;i++) {
        tabPixel[i]=0;
    }

    // parcourt l'ensemble de l'image
    for(x=0;x<img.width();x++) {
        for(y=0;y<img.height();y++) {
            i = img.pixel(x,y);
            // choisi la couleur selon le mode souhaité
            switch (mode) {
                 case 1 :
                    indice = qGray(i);
                    break;
                 case 2 :
                    indice = qBlue(i);
                    break;
                 case 3 :
                    indice = qGreen(i);
                    break;
                 case 4 :
                    indice = qRed(i);
                    break;
                }
            // incrémente de 1 l'indice du tableau
            tabPixel[indice]++;
        }
    }

}

// renvoi le tableau
int* Histogramme::getTab() {
    return this->tabPixel;
}

// permet de récupérer le nombre de pixel cumulé du tableau tab_pixel jusque l'indice j
int Histogramme::getPixelCumul(int j) {
    int res = 0;

    for(int i=0; i<j; i++) {
            res+=tabPixel[i];
    }

    return res;

}

// permet de récupérer le nombre de pixel cumulé du tableau tab jusque l'indice j
int Histogramme::getPixelCumul(int* tab, int j) {
    int res = 0;

    for(int i=0; i<j; i++) {
            res+=tab[i];
    }

    return res;

}

// retourne le nombre de pixel max tu tableau tab_pixel
int Histogramme::getMax() {
    int max = 0;
    for(int i=0; i<256; i++) {
        if(tabPixel[i]>max)
                max=tabPixel[i];
    }

    return max;
}

// retourne l'indice du tableau tab_pixel aillant le nombre max d'occurence
int Histogramme::getMaxIndice() {
    int max = 0;
    for(int i=0; i<256; i++) {
        if(tabPixel[i]>max)
                max=i;
    }

    return max;
}

// retourne l'indice du tableau tab_pixel aillant le nombre min d'occurence
int Histogramme::getMinIndice() {
    int min = tabPixel[0];
    for(int i=0; i<256; i++) {
        if(tabPixel[i]<min && tabPixel[i]!=0)
                min=i;
    }

    return min;
}

// retourne l'indice du tableau tab aillant le nombre max d'occurence
int Histogramme::getMaxIndice(int* tab) {
    int max = 0;
    for(int i=0; i<256; i++) {
        if(tab[i]>max)
                max=i;
    }

    return max;
}

// retourne l'indice du tableau tab aillant le nombre min d'occurence
int Histogramme::getMinIndice(int* tab) {
    int min = tab[0];
    for(int i=0; i<256; i++) {
        if(tab[i]<min && tab[i]!=0)
                min=i;
    }

    return min;
}

// remplit l'image de l'histo en pixels blancs
Image Histogramme::setHisto_blanc() {
    Image res = QImage(300,300, Image::Format_RGB32);
    int x, y;
    // parcourt l'ensemble de l'image et fixe un pixel blanc
    for(x=0;x<300;x++) {
        for(y=0;y<300;y++) {
            res.setPixel(x, y, qRgb(255, 255, 255));
        }
    }
    return res;
}
